#include "attributeeditor.h"
#include "ui_attributeeditor.h"

#include "uml/class/classattribute.h"
#include "uml/class/umlclassitem.h"
#include "uml/class/classmethod.h"


AttributeEditor::AttributeEditor(UmlClassItem *classItem, ClassAttribute *att) :
    ui(new Ui::AttributeEditor),
    _classItem(classItem)
{
    ui->setupUi(this);

    this->_attHighlighter = new UmlMethodHighlighter(this->ui->textEditPreview->document(), this->_classItem->project()->dataTypes());
    this->_getterHighlighter = new UmlMethodHighlighter(this->ui->textEditGetter->document(), this->_classItem->project()->dataTypes());
    this->_setterHighlighter = new UmlMethodHighlighter(this->ui->textEditSetter->document(), this->_classItem->project()->dataTypes());

    QWidget::setAttribute(Qt::WA_DeleteOnClose);

    this->_att = 0;
    this->_getter = 0;
    this->_setter = 0;

    if (!att) {
        this->_att = new ClassAttribute();
    } else {
        this->_att = att;
    }

    this->ui->nameLineEdit->setText(this->_att->name());
    switch (this->_att->visibility()) {
        case PUBLIC : this->ui->visibilityComboBox->setCurrentIndex(0); break;
        case PRIVATE : this->ui->visibilityComboBox->setCurrentIndex(1); break;
        case PROTECTED : this->ui->visibilityComboBox->setCurrentIndex(2); break;
    }

    if (this->_att->hasGetter()) {
        this->ui->createGetterCheckBox->setChecked(this->_att->hasGetter());
        this->ui->textEditGetter->setText(this->_att->getGetter()->umlText());
    }

    if (this->_att->hasSetter()) {
        this->ui->createSetterCheckBox->setChecked(this->_att->hasSetter());
        this->ui->textEditSetter->setText(this->_att->getSetter()->umlText());
    }

    // init checkboxes
    this->ui->textEditGetter->setEnabled(this->_att->hasGetter());
    this->ui->textEditSetter->setEnabled(this->_att->hasSetter());

    QObject::connect(this->ui->pushButtonSave, SIGNAL(clicked()), this, SLOT(save()));

    // getter preview
    QObject::connect(this->ui->createGetterCheckBox, SIGNAL(toggled(bool)), this->ui->textEditGetter, SLOT(setEnabled(bool)));
    QObject::connect(this->ui->createGetterCheckBox, SIGNAL(toggled(bool)), this, SLOT(update()));
    QObject::connect(this->ui->nameLineEdit, SIGNAL(textChanged(QString)), this, SLOT(update()));
    QObject::connect(this->ui->visibilityComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(update()));
    QObject::connect(this->ui->datatypeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(update()));

    // setter preview
    QObject::connect(this->ui->createSetterCheckBox, SIGNAL(toggled(bool)), this->ui->textEditSetter, SLOT(setEnabled(bool)));
    QObject::connect(this->ui->createSetterCheckBox, SIGNAL(toggled(bool)), this, SLOT(update()));
    QObject::connect(this->ui->nameLineEdit, SIGNAL(textChanged(QString)), this, SLOT(update()));
    QObject::connect(this->ui->visibilityComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(update()));
    QObject::connect(this->ui->datatypeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(update()));

}

AttributeEditor::~AttributeEditor()
{
    delete this->_getterHighlighter;
    delete this->_setterHighlighter;
    delete this->_attHighlighter;
    delete ui;
}

void AttributeEditor::setClassItem(UmlClassItem *classItem)
{
    this->_classItem = classItem;
}

void AttributeEditor::setAttribute(ClassAttribute *att){
    this->_att = att;
    this->ui->nameLineEdit->setText(att->name());
    this->ui->visibilityComboBox->setSelectedVisibility(att->visibilityToString());
}

void AttributeEditor::setDatatypes(DatatypeDictionary *datatypes)
{
    this->_datatypes = datatypes;
    this->ui->datatypeComboBox->setModel(this->_datatypes);

    if (this->_att) {
        int index = this->_datatypes->indexByLabel(this->_att->returnType());

        if (index >= 0) {
            this->ui->datatypeComboBox->setCurrentIndex(index);
        }
    }
}

void AttributeEditor::changeEvent(QEvent *e)
{
    QDialog::changeEvent(e);
    switch (e->type()) {
    case QEvent::LanguageChange:
        ui->retranslateUi(this);
        break;
    default:
        break;
    }
}

ClassAttribute* AttributeEditor::save()
{
    this->_att->setClassItem(this->_classItem);
    this->_att->setText(this->ui->nameLineEdit->text());
    this->_att->setVisibility(this->ui->visibilityComboBox->currentText());
    this->_att->setReturnType(this->ui->datatypeComboBox->currentText());

    this->_classItem->appendAtt(this->_att);

    if (this->ui->createGetterCheckBox->isChecked()) {
        ClassMethod *getter = new ClassMethod(this->_classItem);
        getter->setText(QString("get%1").arg(this->capitalize(this->_att->name())));
        getter->setVisibility("public");
        this->_att->setGetter(getter);
        this->_classItem->appendMeth(getter);
    }

    if (this->ui->createSetterCheckBox->isChecked()) {
        ClassMethod *setter = new ClassMethod(this->_classItem);
        setter->setText(QString("set%1").arg(this->capitalize(this->_att->name())));
        setter->setVisibility("public");

        ClassAttribute *arg = new ClassAttribute(this->_classItem);
        arg->setText(this->_att->name());
        arg->setReturnType(this->_att->returnType());

        setter->appendArg(arg);

        this->_att->setGetter(setter);
        this->_classItem->appendMeth(setter);
    }

    this->done(QDialog::Accepted);

    return this->_att;
}


void AttributeEditor::update()
{
    QString name = this->ui->nameLineEdit->text();
    QString returnType = this->ui->datatypeComboBox->currentText();
    QString visibility = this->ui->visibilityComboBox->currentText();

    QString attText;
    if (visibility == "public") attText += "+ ";
    if (visibility == "private") attText += "- ";
    if (visibility == "protected") attText += "# ";
    attText += returnType + " : " + name;

    QString getterText = QString("+ get%1() : %2")
                         .arg(this->capitalize(name))
                         .arg(returnType);

    QString setterText = QString("+ set%1( %2 : %3) : void")
                         .arg(this->capitalize(name))
                         .arg(name)
                         .arg(returnType);

    this->ui->textEditPreview->setText(attText);
    this->ui->textEditGetter->setText(getterText);
    this->ui->textEditSetter->setText(setterText);
}

QString AttributeEditor::capitalize(QString string)
{
    QString cap = string.at(0).toUpper();

    return string.replace(0, 1, cap);
}
